package com.mofabot.bot

import cn.hutool.core.util.IdUtil
import cn.hutool.core.util.StrUtil
import com.mofabot.annotation.Command
import com.mofabot.domain.MessageRecord
import com.mofabot.event.OnMemberAddGroup
import com.mofabot.service.MessageRecordService
import com.mofabot.utils.LogUtil.Companion.log
import com.mofabot.utils.RedisUtil
import com.mofabot.utils.SpringUtils
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import lombok.extern.slf4j.Slf4j
import org.apache.commons.lang3.StringUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Lazy
import org.telegram.telegrambots.bots.DefaultBotOptions
import org.telegram.telegrambots.bots.TelegramLongPollingBot
import org.telegram.telegrambots.meta.api.methods.botapimethods.BotApiMethodMessage
import org.telegram.telegrambots.meta.api.methods.send.SendMessage
import org.telegram.telegrambots.meta.api.methods.updatingmessages.DeleteMessage
import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageText
import org.telegram.telegrambots.meta.api.objects.Message
import org.telegram.telegrambots.meta.api.objects.Update
import org.telegram.telegrambots.meta.exceptions.TelegramApiException
import java.util.*
import kotlin.reflect.full.findAnnotation


/**
 * 机器人类
 *
 * @since 2023/09/19.
 * @author ll
 */
@Slf4j
class BotApp(options: DefaultBotOptions?, botToken: String?) : TelegramLongPollingBot(options, botToken) {
    @Autowired
    private lateinit var botConfig: BotConfig

    @Lazy
    @Autowired
    private lateinit var memberAddGroup: OnMemberAddGroup

    @Lazy
    @Autowired
    private lateinit var messageRecordService: MessageRecordService

    @Autowired
    private lateinit var redisUtil: RedisUtil

    override fun getBotUsername(): String {
        return botConfig.botName
    }

    override fun onUpdateReceived(update: Update) {
        log.debug("receipt update from telegram: {}", update)
        if (update.hasChatJoinRequest()) {
            memberAddGroup.handle(update)
        }
        if (update.hasMessage() && update.message.hasText()) {
            saveMsg(update);

            val messageText = update.message.text.replace("@${botConfig.botName}", "")
            val chatId = update.message.chatId
            val c = Router.ROUTE[messageText.split(" ")[0]] ?: return
            c::class.findAnnotation<Command>()?.let {
                val uid = update.message.from.id
                //如果是吵架管理员，拥有所有权限
                if (botConfig.ownerId.toLong() == uid) {
                    c.handleCommand(update)
                    return
                }
                if (it.onlySuperAdmin) {
                    sendReplyMessageAndDelete(update.message.messageId, chatId, "对不起,您不是超级管理员！", 2)
                    return
                }
                if (it.onlyAdmin) {
                    val admin = if (update.message.chat.type == "private") {
                        redisUtil.get("admin:$uid")
                    } else {
                        redisUtil.get("admin:${update.message.chatId}:$uid")
                    }
                    if (StringUtils.isBlank(admin)) {
                        sendReplyMessageAndDelete(update.message.messageId, chatId, "对不起,您不是管理员！", 2)
                        return
                    }
                }
                c.handleCommand(update)
            }
        } else if (update.hasCallbackQuery()) {
            val clsName = StrUtil.lowerFirst(update.callbackQuery.data.split(":")[0])
            val instance: ICommandBase = SpringUtils.getBean(clsName)
            instance.handleQuery(update)
        }
    }

    private fun saveMsg(update: Update) {
        val msg = update.message

        val message = MessageRecord()
        message.id = IdUtil.getSnowflakeNextId()
        message.tgMsgId = msg.messageId.toLong()
        message.tgUserId = msg.from.id
        message.tgUserName = msg.from.userName
        message.tgUserNickName = msg.from.firstName + msg.from.lastName
        message.content = msg.text
        message.createAt = Date()

//        messageRecordService.save(message);
    }

    fun sendMessage(chatId: Long, textToSend: String): Message? {
        return sendReplyMessage(null, chatId, textToSend)
    }

    fun sendMessage(message: BotApiMethodMessage): Message? {
        return try {
            execute(message)
        } catch (e: TelegramApiException) {
            log.error(e.message)
            null;
        }
    }

    fun sendEditMessageText(messageId: Int, chatId: Long, text: String): Boolean {
        val message = EditMessageText()
        message.chatId = chatId.toString()
        message.text = text
        message.messageId = messageId
        return try {
            execute(message)
            true
        } catch (e: TelegramApiException) {
            log.error(e.message)
            false
        }
    }

    fun sendEditMessageTextAndDelete(messageId: Int, chatId: Long, text: String, timeSecond: Long): Boolean {
        return try {
            sendEditMessageText(messageId, chatId, text)
            runBlocking {
                delay(timeSecond * 1000)
                sendDeleteMessage(messageId, chatId.toString())
            }
            true
        } catch (e: TelegramApiException) {
            log.error(e.message)
            false
        }
    }

    fun sendReplyMessage(messageId: Int?, chatId: Long, textToSend: String): Message? {
        val message = SendMessage()
        message.setChatId(chatId)
        message.replyToMessageId = messageId
        message.text = textToSend
        return sendMessage(message)
    }

    fun sendReplyMessageAndDelete(messageId: Int, chatId: Long, textToSend: String, timeSecond: Long): Boolean? {
        sendReplyMessage(messageId, chatId, textToSend)
        runBlocking {
            delay(timeSecond * 1000)
            sendDeleteMessage(messageId, chatId.toString())
        }
        return true
    }


    fun sendDeleteMessage(messageId: Int, chatId: String): Boolean {
        return try {
            val d = DeleteMessage()
            d.chatId = chatId
            d.messageId = messageId
            execute(d)
            true
        } catch (e: TelegramApiException) {
            log.error(e.message)
            false
        }
    }

    fun sendAndDelete(message: BotApiMethodMessage, timeSecond: Long): Boolean {
        return try {
            val sendMessage = sendMessage(message)
            runBlocking {
                delay(timeSecond * 1000)
                sendDeleteMessage(sendMessage!!.messageId, sendMessage.chatId.toString())
            }
            true
        } catch (e: TelegramApiException) {
            log.error(e.message)
            false
        }
    }
}
